package com.hm.service.service.wechat;

import com.alibaba.fastjson2.JSONObject;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Formatter;
import java.util.HashMap;
import java.util.UUID;


@Service
public class WeChatPublicService implements IWeChatPublic {

    private static final Logger logger = LoggerFactory.getLogger(WeChatPublicService.class);

    //微信公众号配置信息
    private static final String appID = "wxdd2002c0c548a1e0";
    private static final String appsecret = "0c00b92f58b84ded4df9c0d7e619d2cc";
    //access_token缓存key
    private static final String WECHAT_ACCESS_TOKEN_KEY = "wechat_access_token_key";
    //jsapi_ticket缓存key
    private static final String WECHAT_JSAPI_TICKET_KEY = "wechat_jsapi_ticket_key";

    @Qualifier("OkHttpClient")
    public OkHttpClient okHttpClient;

    @Qualifier("jedisPool")
    private final JedisPool jedisPool;

    public WeChatPublicService(OkHttpClient okHttpClient, JedisPool jedisPool) {
        this.okHttpClient = okHttpClient;
        this.jedisPool = jedisPool;
    }

    @Override
    public String getAccessToken() {
        /**
         * 1、获取access_token有效期7200秒 需全局缓存
         * 2、获取jsapi_ticket有效期7200秒 需全局缓存
         * 3、生成签名
         */
        //1、获取access_token->先从redis中获取->access_token有效期7200秒 需全局缓存
        try (Jedis jedis = jedisPool.getResource()) {
            //验证码
            boolean exists = jedis.exists(WECHAT_ACCESS_TOKEN_KEY);
            if (exists) {
                //存在则说明没过期
                return jedis.get(WECHAT_ACCESS_TOKEN_KEY);
            }
            //不存在则说明过期了->从新获取
            String reqUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appID + "&secret=" + appsecret;
            Request build = new Request.Builder()//
                    .url(reqUrl)//
                    .build();//
            try (Response response = okHttpClient.newCall(build).execute()) {
                ResponseBody resBody = response.body();
                if (resBody != null) {
                    String jsonString = resBody.string();
                    JSONObject jsonObject = JSONObject.parseObject(jsonString);
                    String accessToken = jsonObject.getString("access_token");
                    //设置保存时间为7200秒
                    jedis.setex(WECHAT_ACCESS_TOKEN_KEY, 7100, accessToken);
                    logger.error("accessToken走请求:" + accessToken);
                    return accessToken;
                } else {
                    logger.error("accessToken获取resBody为null！！ ");
                }
            } catch (Exception e) {
                logger.error("获取accessToken异常：Exception: " + e.getMessage());
            }
        }
        return "";
    }

    @Override
    public String getJsapiTicket(String accessToken) {
        //2、根据access_token获取jsapi_ticket->先从redis中获取->jsapi_ticket有效期7200秒 需全局缓存
        try (Jedis jedis = jedisPool.getResource()) {
            //验证码
            boolean exists = jedis.exists(WECHAT_JSAPI_TICKET_KEY);
            if (exists) {
                //存在则说明没过期
                return jedis.get(WECHAT_JSAPI_TICKET_KEY);
            }
            if (accessToken == null || accessToken.isEmpty()) {
                return "";
            }
            //不存在则说明过期了->从新获取
            String reqUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + accessToken + "&type=jsapi";
            Request build = new Request.Builder()//
                    .url(reqUrl)//
                    .build();//
            try (Response response = okHttpClient.newCall(build).execute()) {
                ResponseBody resBody = response.body();
                if (resBody != null) {
                    String jsonString = resBody.string();
                    JSONObject jsonObject = JSONObject.parseObject(jsonString);
                    String jsapiTicket = jsonObject.getString("ticket");
                    //设置保存时间为7200秒
                    jedis.setex(WECHAT_JSAPI_TICKET_KEY, 7100, jsapiTicket);
                    logger.error("JsapiTicket走请求:" + jsapiTicket);
                    return jsapiTicket;
                } else {
                    logger.error("jsapiTicket获取resBody为null！！ ");
                }
            } catch (Exception e) {
                logger.error("获取jsapiTicket异常：Exception: " + e.getMessage());
            }
        }
        return "";
    }

    @Override
    public HashMap<String, String> generateSignature(String url, String JsapiTicket) {
        String nonceStr = UUID.randomUUID().toString();
        String timestamp = Long.toString(System.currentTimeMillis() / 1000);
        String signature = "";
        HashMap<String, String> data = new HashMap<>();
        //注意这里参数名必须全部小写，且必须有序
        String signature1 = "jsapi_ticket=" + JsapiTicket + "&noncestr=" + nonceStr + "&timestamp=" + timestamp + "&url=" + url;
        //生成最终签名签名
        try {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(signature1.getBytes(StandardCharsets.UTF_8));
            signature = byteToHex(crypt.digest());
        } catch (Exception e) {
            logger.error("生成签名异常：Exception: " + e.getMessage());
        }
        data.put("nonceStr", nonceStr);
        data.put("timestamp", timestamp);
        data.put("signature", signature);
        return data;
    }

    @Override
    public String getOpenid(String code) {
        //本步骤中获取到网页授权access_token的同时，也获取到了openid，snsapi_base式的网页授权流程即到此为止
        //注意：同一个code只能请求一次资源，否则会报错{"errcode":40163,"errmsg":"code been used, rid: 661504e7-286e7255-0db6bc03"}
        String reqUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appID + "&secret=" + appsecret + "&code=" + code + "&grant_type=authorization_code";
        Request build = new Request.Builder()//
                .url(reqUrl)//
                .build();//
        try (Response response = okHttpClient.newCall(build).execute()) {
            ResponseBody resBody = response.body();
            if (resBody != null) {
                String jsonString = resBody.string();
                JSONObject jsonObject = JSONObject.parseObject(jsonString);
                String openid = jsonObject.getString("openid");
                logger.error("openid:" + jsonObject);
                return openid;
            } else {
                logger.error("getOpenid获取resBody为null！！ ");
            }
        } catch (Exception e) {
            logger.error("获取getOpenid异常：Exception: " + e.getMessage());
        }
        return "";
    }

    private static String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash) {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }


}
